package api

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"go-eth-tracker/config"
	"go-eth-tracker/dao"
	"go-eth-tracker/utils"
	"go.uber.org/zap"
	"net/http"
)

var methodAllowed = []string{"getaddress"}

type GeneralHandler struct {
	MssqlDao  *dao.MssqlDao
	LogContext     *zap.Logger
	ApiContext     *Context
	AppConfig      *config.AppConfig
	addressHandler *AddressHandler
}

func (h *GeneralHandler) Dispatch(c *gin.Context) {
	queries := c.Request.URL.Query()
	if c.Request.Method == http.MethodPost {
		queries = c.Request.PostForm
	}

	parameters := make(map[string]string)
	merchantId := queries.Get("mch_id")
	if len(merchantId) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code":    "0001",
			"message": "未提供指定参数 mch_id",
			"success": false,
		})
		return
	}
	parameters["mch_id"] = merchantId

	method := queries.Get("method")
	if len(method) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code":    "0001",
			"message": "未提供指定参数 method",
			"success": false,
		})
		return
	}
	parameters["method"] = method

	sign := queries.Get("sign")
	if len(sign) == 0 {
		c.JSON(http.StatusOK, gin.H{
			"code":    "0001",
			"message": "未提供指定参数 sign",
			"success": false,
		})
		return
	}
	parameters["sign"] = sign

	bizBody := queries.Get("biz_body")
	if len(bizBody) > 0 && !json.Valid([]byte(bizBody)) {
		c.JSON(http.StatusOK, gin.H{
			"code":    "0001",
			"message": "指定参数 biz_body 格式不正确",
			"success": false,
		})
		return
	}
	parameters["biz_body"] = bizBody

	if utils.SliceIndex(len(methodAllowed), func(idx int) bool {
		return methodAllowed[idx] == method
	}) == -1 {
		c.JSON(http.StatusOK, gin.H{
			"code":    "0001",
			"message": "参数 method 无效",
			"success": false,
		})
		return
	}

	merchant := h.ApiContext.GetMerchant(merchantId)
	if merchant == nil {
		c.JSON(http.StatusOK, gin.H{
			"code":    "0004",
			"message": "商户不存在",
			"success": false,
		})
		return
	}

	h.LogContext.Info(fmt.Sprintf("找到商户 %s 的信息", merchantId))
	if !h.AppConfig.Debug {
		if ok, _ := utils.CheckMD5Sign(parameters, (*merchant).ApiKey, h.LogContext); !ok {
			c.JSON(http.StatusOK, gin.H{
				"code":    "0002",
				"message": "验签失败",
				"success": false,
			})
			return
		}
	} else {
		h.LogContext.Info("DEBUG 模式")
	}

	c.JSON(http.StatusOK, h.execMethod(merchantId, method, bizBody))
	//c.JSON(http.StatusOK, gin.H{
	//	"code":    "0000",
	//	"message": "OK",
	//	"success": true,
	//	"data":    "SUCCESS",
	//})
	return

	// c.AbortWithStatus(http.StatusNotFound)
}

func (h *GeneralHandler) execMethod(merchantId string, method string, bizContent string) map[string]interface{} {
	h.LogContext.Info(fmt.Sprintf("执行 %s", method))

	if method == "getaddress" {
		h.LogContext.Info(fmt.Sprintf("开始获取收款地址信息，业务内容 %s", bizContent))
		if h.addressHandler == nil {
			h.addressHandler = &AddressHandler{
				MssqlDao:     h.MssqlDao,
				LogContext:   h.LogContext,
				MasterPubKey: h.AppConfig.MasterPubKey,
				ApiContext:   h.ApiContext,
			}
		}


		var addrReq AddressRequest
		err := json.Unmarshal([]byte(bizContent), &addrReq)
		if err != nil {
			return h.getError("无效的 biz_content 数据")
		}

		addrResp := h.addressHandler.GetAddress(merchantId, addrReq.UserId)
		if addrResp == nil {
			return h.getError("地址获取失败")
		}

		return gin.H{
			"code":    "0000",
			"message": "OK",
			"success": true,
			"data":    addrResp,
		}
	}

	return h.getError(fmt.Sprintf("未实现 %s 的方法", method))
}

func (h *GeneralHandler) getError(message string) map[string]interface{} {
	return gin.H{
		"code":    "0002",
		"message": message,
		"success": false,
	}
}
